package org.apache.solr.handler.dataimport.scheduler;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * TIMETASK 设置 
 * @author IMZHANGJIE.CN
 *
 */
public abstract class BaseTimerTask extends TimerTask {
	
	protected SolrDataImportProperties p;	
	protected String server;
	protected String port;
	protected String webapp;
	protected String cores;
	
	protected String enabled;
	protected String[] coresArr;
	protected String params;
	protected String beginTime;
	protected String interval;
	protected String type;
	

	protected static final Logger logger = LoggerFactory.getLogger(BaseTimerTask.class);

	public BaseTimerTask(String webAppName, Timer t, String type) throws Exception {
		this.type = type;
		// load properties from global dataimport.properties
		p = new SolrDataImportProperties();
		reloadParams();
		fixParams(webAppName);
		if (!enabled.equals("1"))
			throw new Exception(type+" Schedule disabled");	
		logger.info("<index update process> Core identified in dataimport.properties. Sync active for: " + cores);
	}

	protected void reloadParams() {
		p.loadProperties(true);
		server = p.getProperty(SolrDataImportProperties.SERVER);
		port = p.getProperty(SolrDataImportProperties.PORT);
		webapp = p.getProperty(SolrDataImportProperties.WEBAPP);
		
		enabled = p.getProperty(type+"."+SolrDataImportProperties.ENABLED);
		cores = p.getProperty(type+"."+SolrDataImportProperties.CORES);
		coresArr = cores != null ? cores.split(",") : null;		
		params = p.getProperty(type+"."+SolrDataImportProperties.PARAMS);
		beginTime = p.getProperty(type+"."+SolrDataImportProperties.BEGINTIME);
		interval = p.getProperty(type+"."+SolrDataImportProperties.INTERVAL);
	}

	protected void fixParams(String webAppName) {
		if (server == null || server.isEmpty())
			server = "localhost";
		if (port == null || port.isEmpty())
			port = "8983";
		if (webapp == null || webapp.isEmpty())
			webapp = webAppName;
		if (beginTime == null || beginTime.isEmpty())
			beginTime = "00:00:00";
		if (interval == null || interval.isEmpty() || getIntervalInt() <= 0)
			interval = "0";
	}

	protected void prepUrlSendHttpPost(String type,String coreName,String params) {
		StringBuffer paramBuffer = new StringBuffer(params);
		StringBuffer coreUrl = new StringBuffer("http://");
		coreUrl.append(server).append(":").append(port).append("/").append(webapp).append("/").append(coreName);
		if(SolrDataImportProperties.REMOVE_INDEX.equals(type)){
			coreUrl.append("/update");
			String query = p.getProperty(type+"."+SolrDataImportProperties.QUERY+"."+coreName);
			if(query == null || "".equals(query)){
				return;
			}
			paramBuffer.append("&stream.body=").append(query);
		}else if(SolrDataImportProperties.OPTIMIZED_INDEX.equals(type)){
			coreUrl.append("/update");
		}else{
			coreUrl.append("/dataimport");
			String entities = null;
			if(SolrDataImportProperties.DELTA_INDEX.equals(type)){
				entities = p.getProperty(type+"."+SolrDataImportProperties.ENTITY+"."+coreName);
			}else if(SolrDataImportProperties.FULL_INDEX.equals(type)){
				entities = p.getProperty(type+"."+SolrDataImportProperties.ENTITY+"."+coreName);
			}
			if(entities != null && !"".equals(entities) && !"".equals(entities.replace(" ", ""))){
				entities = entities.trim();
				if(entities.indexOf("[") != -1 && entities.indexOf("]") != -1 
						&& entities.indexOf("-") != -1){//支持配置方式 dmpreport[0-10]
					String pre = entities.split("\\[")[0];
					String n = entities.split("\\[")[1].replace("]", "");
					String [] nums = n.split("-");
					Integer start = Integer.parseInt(nums[0].trim());
					Integer end = Integer.parseInt(nums[1].trim());
					for(int i = start;i <= end;i++){
						paramBuffer.append("&entity=").append(pre+i);
					}
				}else{//支持配置方式dmpreport0,dmpreport1.....
					String [] entitys = entities.split(",");
					if(entitys.length > 0){
						for(String entity : entitys){
							paramBuffer.append("&entity=").append(entity);
						}
					}
				}
			}
		}
		sendHttpPost(coreUrl.toString(), coreName, paramBuffer.toString());
	}
	
	protected void sendHttpPost(String completeUrl, String coreName,String params) {
		DateFormat df = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss SSS");
		Date startTime = new Date();

		// prepare the core var
		String core = coreName == null ? "" : "[" + coreName + "] ";

		logger.info(core + "<index update process> Process started at .............. " + df.format(startTime));

		try {

			URL url = new URL(completeUrl);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();

			conn.setRequestMethod("POST");
			conn.setRequestProperty("type", "submit");
			conn.setDoOutput(true);

			if(params != null && !"".equals(params)){
				logger.info("<index update process> params:"+params);
				conn.getOutputStream().write(params.getBytes("utf-8"));
			}
			
			// Send HTTP POST
			conn.connect();

			logger.info(core + "<index update process> Full URL\t\t\t\t" + conn.getURL());
			logger.info(core + "<index update process> Response message\t\t\t" + conn.getResponseMessage());
			logger.info(core + "<index update process> Response code\t\t\t" + conn.getResponseCode());

			// listen for change in properties file if an error occurs
//			if (conn.getResponseCode() != 200) {
//				reloadParams();
//			}

			conn.disconnect();
			logger.info(core
					+ "<index update process> Disconnected from server\t\t"
					+ server);
			Date endTime = new Date();
			logger.info(core
					+ "<index update process> Process ended at ................ "
					+ df.format(endTime));
		} catch (MalformedURLException mue) {
			logger.error("Failed to assemble URL for HTTP POST", mue);
		} catch (IOException ioe) {
			logger.error(
					"Failed to connect to the specified URL while trying to send HTTP POST",
					ioe);
		} catch (Exception e) {
			logger.error("Failed to send HTTP POST", e);
		}
	}

	public int getIntervalInt() {
		try {
			return Integer.parseInt(interval);
		} catch (NumberFormatException e) {
			logger.info("Unable to convert '"+type+"inteval' to number. do't rebuild index.",e);
			return 0; 
		}
	}

	public Date getBeginTime() {
		Date beginDate = null;
		try {
			SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");
			String dateStr = sdfDate.format(new Date());
			beginDate = sdfDate.parse(dateStr);
			if (beginTime == null
					|| beginTime.isEmpty()) {
				return beginDate;
			}
			if (beginTime.matches("\\d{2}:\\d{2}:\\d{2}")) {
				SimpleDateFormat sdf = new SimpleDateFormat(
						"yyyy-MM-dd HH:mm:ss");
				beginDate = sdf.parse(dateStr + " " + beginTime);
				Calendar calendar = Calendar.getInstance();
				calendar.setTime(beginDate);
				calendar.add(Calendar.HOUR, -8);//UTC时间减去8个小时
				beginDate = calendar.getTime();					
				if(beginDate.getTime() < new Date().getTime()){//如果开始时间小于现在的时间，则设置为隔天开始
					calendar = Calendar.getInstance();
					calendar.setTime(beginDate);
					calendar.add(Calendar.DATE, 1);
					beginDate = calendar.getTime();
				}
			} else if (beginTime
					.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {
				SimpleDateFormat sdf = new SimpleDateFormat(
						"yyyy-MM-dd HH:mm:ss");
				beginDate = sdf.parse(beginTime);
				Calendar calendar = Calendar.getInstance();
				calendar.setTime(beginDate);
				calendar.add(Calendar.HOUR, -8);
				beginDate = calendar.getTime();					
			}
			return beginDate;
		} catch (ParseException e) {
			logger.warn("Unable to convert '"+type+".beginTime' to date. use now time.",	e);
			return beginDate;
		}
	}
	
}
